using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils;

namespace ICSharpCode.AvalonEdit.Editing
{
	sealed class CaretLayer : Layer
	{
		bool _isVisible;
		Rect _caretRectangle;
	    readonly DispatcherTimer _caretBlinkTimer = new DispatcherTimer();
		bool _blink;
		
		public CaretLayer(TextView textView) : base(textView, KnownLayer.Caret)
		{
			IsHitTestVisible = false;
			_caretBlinkTimer.Tick += caretBlinkTimer_Tick;
		}

		void caretBlinkTimer_Tick(object sender, EventArgs e)
		{
			_blink = !_blink;
			InvalidateVisual();
		}
		
		public void Show(Rect caretRectangle)
		{
			_caretRectangle = caretRectangle;
			_isVisible = true;
			InvalidateVisual();
			StartBlinkAnimation();
		}
		
		public void Hide()
		{
		    if (!_isVisible) return;
		    _isVisible = false;
		    StopBlinkAnimation();
		    InvalidateVisual();
		}
		
		void StartBlinkAnimation()
		{
			var blinkTime = Win32.CaretBlinkTime;
		    if (!(blinkTime.TotalMilliseconds >= 0)) return;
		    _blink = false;
		    caretBlinkTimer_Tick(null, null);
		    _caretBlinkTimer.Interval = blinkTime;
		    _caretBlinkTimer.Start();
		}
		
		void StopBlinkAnimation()
		{
			_caretBlinkTimer.Stop();
		}
		
		internal Brush CaretBrush;
		
		protected override void OnRender(DrawingContext drawingContext)
		{
			base.OnRender(drawingContext);
		    if (!_isVisible || !_blink) return;
		    var caretBrush = CaretBrush ?? (Brush)textView.GetValue(TextBlock.ForegroundProperty);
		    var r = new Rect(_caretRectangle.X - textView.HorizontalOffset,
		                     _caretRectangle.Y - textView.VerticalOffset,
		                     _caretRectangle.Width,
		                     _caretRectangle.Height);
		    drawingContext.DrawRectangle(caretBrush, null, PixelSnapHelpers.Round(r, PixelSnapHelpers.GetPixelSize(this)));
		}
	}
}
